package com.jackmo.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
//import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class ApiLogAspect {

    // 定义切点：拦截所有Controller层方法
    @Pointcut("execution(* com.jackmo.controller..*.*(..))")
    public void apiPointcut() {}

    // 环绕通知
    @Around("apiPointcut()")
    public Object logApiRequest(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        
        // 记录请求日志
        log.info("\n" +
                "=============================== Request Start ===============================\n" +
                "IP         : {}\n" +
                "URL        : {}\n" +
                "HTTP Method: {}\n" +
                "Class.Method: {}.{}\n" +
                "Params     : {}\n" +
                "=============================== Request End   ===============================",
                request.getRemoteAddr(),
                request.getRequestURL().toString(),
                request.getMethod(),
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(),
                Arrays.toString(joinPoint.getArgs()));

        // 记录方法执行时间
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // 执行目标方法
        long endTime = System.currentTimeMillis();

        // 记录响应日志
        log.info("\n" +
                "=============================== Response Start ===============================\n" +
                "Class.Method: {}.{}\n" +
                "Time-Cost  : {} ms\n" +
                "Result     : {}\n" +
                "=============================== Response End   ===============================",
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(),
                (endTime - startTime),
                result != null ? result.toString() : "null");

        return result;
    }

    // 异常通知
    @AfterThrowing(pointcut = "apiPointcut()", throwing = "e")
    public void logException(Throwable e) {
        log.error("\n" +
                "=============================== Exception Occurred ===============================\n" +
                "Error Type : {}\n" +
                "Message    : {}\n" +
                "Stack Trace: {}\n" +
                "================================================================================",
                e.getClass().getName(),
                e.getMessage(),
                Arrays.toString(e.getStackTrace()));
    }
}